ホームに戻る
出典 :
関連 :
目次 :
コンバーターとは
WPFのデータバインディングにおいて、ソースとターゲットとの間で形式(型や書式など)を変換する機構のこと。
例えば TextBox に DateTime 型をバインドし、そのうち年、月、日のみを表示するよう変換する、といったことが可能となる。
コンバーターの実装
コード
System.Windows.Data.IValueConverterインタフェースを実装する。実装が必要なメソッドは以下のふたつ。
Convert()- ソースからターゲットへの変換
ConvertBack()- ターゲットからソースへの変換
変換先のプロパティ( Convert() : ターゲット / ConvertBack() : ソース )を更新しない場合は、return DependencyProperty.UnsetValue;とする。
using System.Globalization;
using System.Windows.Data;
namespace _Converter;
// コンバーター
// DateTime ⇒ String
[ValueConversion(typeof(DateTime), typeof(String))]
public class DateConverter : IValueConverter
{
// ソース ⇒ ターゲット変換
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// 日付形式の文字列に変換して返す
DateTime date = (DateTime)value;
return date.ToShortDateString();
}
// ターゲット ⇒ ソース変換
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// 日時に変換可能であれば変換して返す
string strValue = value as string;
DateTime resultDateTime;
if (DateTime.TryParse(strValue, out resultDateTime))
{
return resultDateTime;
}
// 変換できない場合は何もしない
// (値を更新しない)
return DependencyProperty.UnsetValue;
}
}
Convert() / ConvertBack() の詳細
引数及び戻り値は下表のとおり。
|
Convert() |
ConvertBack() |
| 機能 |
ソース値をターゲット値に変換する (ソース値からターゲット値を得る) |
ターゲット値をソース値に変換する (ターゲット値からソース値を得る) |
| 戻り値 |
object |
(変換後の)ターゲット値 |
object |
(変換後の)ソース値 |
| 引数 |
object |
(変換前の)ソース値 |
object |
(変換前の)ターゲット値 |
| Type |
変換後(ターゲット値)の型 |
Type |
変換後(ソース値)の型 |
| object |
ConverterParameterとして渡されたパラメータ |
object |
ConverterParameterとして渡されたパラメータ |
| CultureInfo |
ConverterCultureとして渡されたカルチャ |
CultureInfo |
ConverterCultureとして渡されたカルチャ |
ConverterParameterおよびConverterCultureはデータバインディングの構成時に指定する。
省略時はともに、既定値であるnullが格納される。いずれもConverterのメンバではなく、Bindingのメンバである点に注意。
ConverterCultureはロケールの情報を保持し、桁区切りや月日の並び順に影響する。多国籍対応を行う場合でなければ指定する必要は特に無い。
XAML
作成したコンバーターを親要素にリソースとして登録することで、デザインから参照することが可能となる。
このとき、コンバーターはStaticResourceとする必要がある(DynamicResourceはエラーとなる)。
<
Window
xmlns:conv=
"clr-namespace:_Converter">
:
<!-- コードで作成したコンバータ―をリソースに登録 -->
<!-- キー : dateConverter -->
<
Window.Resources>
<
conv:DateConverter
x:Key=
"dateConverter"/>
</
Window.Resources>
:
<!-- コンバーター(キー : dateConverter )を適用 -->
<!-- StaticResource として参照 -->
<
TextBlock Name=
"StartDateDTKey" Grid.Row=
"2" Grid.Column=
"1"
Text="{Binding
Path=StartDate,
Converter={
StaticResource dateConverter}}"
Style=
"{StaticResource textStyleTextBlock}"/>
:
</
Window>
応用#1 : ラジオボタンを双方向バインディングする

チェックされたラジオボタンに対応する列挙値(Enum)を取得したい場合、以下のように実装する。
PropertyChanged 、Reactive の実装は省略。
コード : コンバーターの定義
using System.Globalization;
using System.Windows.Data;
namespace _Converter
// 列挙体の定義
public enum mode
{
Simple,
Detail
}
// Enum ⇒ Bool 変換用コンバーター
public class EnumToBoolConverter : IValueConverter
{
// ソース ⇒ ターゲット変換
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var paramStr = parameter as string;
// 比較値が null または
// ソース値が定義域に含まれない場合は値を更新しない
if ( paramStr is null ||
!Enum.IsDefined(targetType, value) )
{
return DependencyProperty.UnsetValue;
}
// ソース値が比較値に一致すれば true 、
// そうでなければ false を返す
return Enum.Parse( value.GetType(), paramStr ).Equals(value);
}
// ターゲット ⇒ ソース変換
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var paramStr = parameter as string;
// 比較値が null または
// ターゲット値が true でない場合は値を更新しない
if( paramStr is null ||
!true.Equals( value ) )
{
return DependencyProperty.UnsetValue;
}
return Enum.Parse( targetType, paramStr );
}
}
XAML : ラジオボタンの配置、コンバーターの適用
<
Window
xmlns:res=
"clr-namespace:_Converter">
:
<
StackPanel>
<
StackPanel.Resources>
<!-- コンバーター EtoB 宣言 -->
<
res:EnumToBoolConverter
x:Key=
"EtoB" />
</
StackPanel.Resources>
<!-- RadioButton -->
<!-- ターゲット : IsChecked (bool) -->
<!-- ソース : ModeValue (mode) -->
<!-- コンバーター : EtoB -->
<!-- 「簡易」- ConverterParameter = Simple ( mode.Simple ) -->
<
RadioButton Content=
"簡易"
IsChecked=
"{Binding ModeValue, Converter={StaticResource EtoB}, Mode=TwoWay, ConverterParameter=Simple}" />
<!-- 「詳細」- ConverterParameter = Detail ( mode.Detail ) -->
<
RadioButton Content=
"詳細"
IsChecked=
"{Binding ModeValue, Converter={StaticResource EtoB}, Mode=TwoWay, ConverterParameter=Detail}" />
:
</
StackPanel>
:
</
Window>
解説

ソース値を変更すると
Convert()が呼ばれ、ソース値が
valueに、
ConverterParameter(
mode.Simple または
mode.Detail )が
parameterに渡される。
parameterを比較値として用い、
valueが
parameterに一致する場合に
Convert()が
trueを返すため、対応するラジオボタンがチェックされる。
逆にチェック状態を変更すると
ConvertBack()が呼ばれ、
ConverterParameterで指定された列挙子がソースに反映される。
注意が必要な点として、ラジオボタンのチェック状態を変更すると「チェックされた」ラジオボタンと、「チェックを外された」ラジオボタンの双方で
CheckedChangedイベントが発生するため、
ConvertBack()もそれぞれで(計2回)コールされる。
ソースに反映するのはチェックされたラジオボタンであるため、
valueが
true(チェックされている)の場合のみソース値の変更を行う。
応用#2 : bool を指定した Visibility にバインドする
コントロールの可視性(Visibility)をbool値によって切り替えられるコンバーターの例を示す。
ソースがtrueの場合はCollapsed、falseの場合はVisibleを返すよう、TrueTo、FalseToプロパティをリソース宣言時に指定している。
ここではTrueTo、FalseToにデフォルト値を割り当てていないため、true/falseに対応する値を用途に応じて切り替えることが可能であるが、
毎回指定する必要がある。
コード : コンバーターの定義
using System.Globalization;
using System.Windows.Data;
namespace _Converter;
public class BoolToAnyVisibilityConverter : IValueConverter
{
public Visibility? TrueTo { get; set; } //< ソースが true の場合に返す値
public Visibility? FalseTo { get; set; } //< ソースが false の場合に返す値
// ソース ⇒ ターゲット変換
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// TrueTo が設定されていない場合は例外
if (!TrueTo.HasValue)
{
throw new InvalidOperationException($"{nameof(TrueTo)}にVisibilityが設定されていません");
}
// FalseTo が設定されていない場合は例外
if (!FalseTo.HasValue)
{
throw new InvalidOperationException($"{nameof(FalseTo)}にVisibilityが設定されていません");
}
// ソースが bool でない場合は値を更新しない
if (!(value is bool b)) { return DependencyProperty.UnsetValue; }
// ソース(bool)が true の場合は TrueTo 、false の場合は FalseTo を返す
return b ? TrueTo : FalseTo;
}
// ターゲット ⇒ ソース変換 : 何もしない
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
XAML : コンバーターの適用
ここでTrueTo、FalseToに値を設定する。
<
Window
xmlns:res=
"clr-namespace:_Converter">
:
<
StackPanel>
<
StackPanel.Resources>
<!-- コンバーター宣言 -->
<!-- TrueTo に Collapsed 、FalseTo に Visible を設定 -->
<
res:BoolToAnyVisibilityConverter
x:Key=
"BoolToCollapse" TrueTo=
"Collapsed" FalseTo=
"Visible"/>
</
StackPanel.Resources>
:
</
StackPanel>
:
</
Window>